<template>
  <div id="three"></div>
  <Popover ref="popoverRef" :top="popoverTop" :left="popoverLeft" :data="popoverData"></Popover>
</template>

<script lang="ts" setup name="Sence">
/* eslint-disable */
import { ref, onMounted, type Ref } from 'vue';
import Viewer, { type Animate } from '@/modules/Viewer';
import Floors from '@/modules/Floors';
import ModelLoader from '@/modules/ModelLoder';
import * as THREE from 'three';
import gsap from 'gsap';
import Event from '@/modules/Viewer/Events';
import BoxHelperWrap from '@/modules/BoxHelperWrap';
import { checkNameIncludes, findParent } from '@/utils';

import Popover from './Popover/index.vue';

let viewer: Viewer;
let modelLoader: ModelLoader;
let boxHelperWrap: BoxHelperWrap;

const popoverRef: Ref = ref(null);
const popoverTop = ref(0);
const popoverLeft = ref(0);
const popoverData = ref<any>({});

let office: any = null;
let oldOffice: any = null;
let dataCenter: any = null;
let oldDataCenter: any = null;
let modelSelect = ['zuo0', 'zuo1', 'zuo2', 'zuo3', 'zuo4', 'zuo5'];
let modelSelectName = '';
let modelMoveName = '';
let isModelSelectName = false;


onMounted(() => {
  init();
  initModel();

  viewer.scene.traverse((item: THREE.Object3D) => {
    console.log(item, '0000000000');
  });
});

const init = () => {
  viewer = new Viewer('three');
  /**坐标轴辅助 */
  // viewer.addAxis();
  // 添加性能状态监测
  viewer.addStats();
  viewer.initRaycaster();

  modelLoader = new ModelLoader(viewer);
  // const floors = new Floors(viewer);
  // floors.addGird();
  // 通过 BoxHelper 可以实现简单的鼠标选中的特效。
  boxHelperWrap = new BoxHelperWrap(viewer);

  viewer.emitter.on(Event.dblclick.raycaster, (list: THREE.Intersection[]) => {
    onMouseClick(list);
  });

  viewer.emitter.on(Event.mousemove.raycaster, (list: THREE.Intersection[]) => {
    onMouseMove(list);
  });

};


// 初始化模型
const initModel = () => {

  // 初始化加载底部线条滚动动画
  modelLoader.loadModelToScene('/models/plane.glb', baseModel => {
    const model = baseModel.gltf.scene;
    model.scale.set(0.0001 * 3, 0.0001 * 3, 0.0001 * 3)
    model.position.set(0, 0, 0);
    model.name = 'plane';
    // 开启模型阴影 数组中移除阴影
    baseModel.openCastShadow();
    const texture = (baseModel.object.children[0] as any).material.map;
    const fnOnj = planeAnimate(texture);
    viewer.addAnimate(fnOnj);
  });


  modelLoader.loadModelToScene('/models/无标题.glb', baseModel => {
  // modelLoader.loadModelToScene('/models/ren.glb', baseModel => {
  // modelLoader.loadModelToScene('/models/datacenter.glb', baseModel => {
    // 设置模型比例
    baseModel.setScalc(0.2);
    // baseModel.object.rotation.y = Math.PI / 2;
    const model = baseModel.gltf.scene;
    model.position.set(0, 0, 0);
    model.name = '机房';
    // 开启模型阴影 数组中移除阴影
    baseModel.openCastShadow();
    dataCenter = baseModel;
    oldDataCenter = model.clone();
    const rackList: any[] = [];
    model.traverse(item => {
      if (checkIsRack(item)) {
        rackList.push(item);
      }
    });
    viewer.setRaycasterObjects(rackList);
  });
};

// 这段代码定义了一个名为 planeAnimate 的函数，该函数接受一个 texture 参数，并返回一个包含动画函数和内容的对象 animateFn
const planeAnimate = (texture: any): Animate => {
  console.log(texture, 'texture');
  // 设置 texture 的 wrapS 和 wrapT 属性为 THREE.RepeatWrapping，表示纹理在 S 和 T 方向上重复贴图。
  texture.wrapS = THREE.RepeatWrapping;
  texture.wrapT = THREE.RepeatWrapping;
  const animateFn = {
    fun: () => {
      // fun 方法定义了纹理的动画逻辑，如果纹理重复次数小于等于 10，则不断增加 repeat.x 和 repeat.y 的值；否则将 repeat.x 和 repeat.y 重置为 0
      const count = texture.repeat.y;
      if (count <= 10) {
        texture.repeat.x += 0.01;
        texture.repeat.y += 0.02;
      } else {
        texture.repeat.x = 0;
        texture.repeat.y = 0;
      }
    },
    // content 属性设置为 viewer，表示该动画函数所作用的内容为 viewer。
    content: viewer,
  };
  // 最后，返回 animateFn 对象作为函数的返回值。
  return animateFn;
}

const onMouseClick = (intersects: THREE.Intersection[]) => {
  // debugger 
  if (!intersects.length) return;
  const selectedObject = intersects[0].object;

  let selectedObjectName = '';
  const findClickModel = (object: any) => {
    if (object.type === 'Group') {
      selectedObjectName = object.name;
    }
    if (object.parent && object.type !== 'Scene') {
      findClickModel(object.parent);
    }
  };
  findClickModel(selectedObject);

};

function checkIsRack(obj: any): boolean {
  return checkNameIncludes(obj, 'rack');
}

const onMouseMove = (intersects: THREE.Intersection[]) => {
  if (!intersects.length) {
    popoverRef.value.setShow(false);
    boxHelperWrap.setVisible(false);
    return;
  }
  const selectedObject = intersects[0].object || {};
  let selectedObjectName = '';
  const findClickModel = (object: any) => {
    if (object.name.includes('rack')) {
      selectedObjectName = object.name;
      return;
    }
    if (object.parent) {
      findClickModel(object.parent);
    }
  };
  findClickModel(selectedObject);
  const rack = findParent(selectedObject, checkIsRack);
  if (rack) {
    boxHelperWrap.attach(rack);
    updateRackInfo(rack.name);
  }
};

const updateRackInfo = (name: string) => {
  if (name) {
    popoverRef.value.setShow(true, { name });
    const event = viewer.mouseEvent as MouseEvent;
    popoverTop.value = event.y + 10;
    popoverLeft.value = event.x + 10;
  } else {
    popoverRef.value.setShow(false);
  }
};



</script>

<style scoped>
#three {
  height: 100%;
  width: 100%;
}
</style>
